//! # 观测性模块测试
//! 
//! 提供观测性模块的全面测试覆盖，包括单元测试、集成测试和性能测试。

use super::*;
use super::traits::*;
use super::context::*;
use super::config::*;
use super::manager::*;
use super::tracing::*;
use super::logging::*;
use super::middleware::*;
use rustcloud_core::{ServiceResult, ServiceError};
use rustcloud_metrics::{MetricsCollector, MetricType, Labels};
use std::sync::Arc;
use std::collections::HashMap;
use tokio::sync::RwLock;
use async_trait::async_trait;
use std::sync::atomic::{AtomicU32, Ordering};

/// 模拟指标收集器
struct MockMetricsCollector {
    metrics: Arc<RwLock<Vec<String>>>,
}

impl MockMetricsCollector {
    fn new() -> Self {
        Self {
            metrics: Arc::new(RwLock::new(Vec::new())),
        }
    }

    async fn get_metrics(&self) -> Vec<String> {
        self.metrics.read().await.clone()
    }

    async fn clear(&self) {
        self.metrics.write().await.clear();
    }
}

#[async_trait]
impl MetricsCollector for MockMetricsCollector {
    async fn record_counter(&self, name: &str, value: f64, labels: Labels) -> ServiceResult<()> {
        let mut metrics = self.metrics.write().await;
        metrics.push(format!("counter:{}:{}:{:?}", name, value, labels));
        Ok(())
    }

    async fn record_gauge(&self, name: &str, value: f64, labels: Labels) -> ServiceResult<()> {
        let mut metrics = self.metrics.write().await;
        metrics.push(format!("gauge:{}:{}:{:?}", name, value, labels));
        Ok(())
    }

    async fn record_histogram(&self, name: &str, value: f64, labels: Labels) -> ServiceResult<()> {
        let mut metrics = self.metrics.write().await;
        metrics.push(format!("histogram:{}:{}:{:?}", name, value, labels));
        Ok(())
    }

    async fn export(&self) -> ServiceResult<()> {
        Ok(())
    }

    fn name(&self) -> &str {
        "mock"
    }
}

/// 模拟观测性指标收集器
struct MockObservabilityMetricsCollector {
    metrics: Arc<RwLock<Vec<String>>>,
}

impl MockObservabilityMetricsCollector {
    fn new() -> Self {
        Self {
            metrics: Arc::new(RwLock::new(Vec::new())),
        }
    }

    async fn get_metrics(&self) -> Vec<String> {
        self.metrics.read().await.clone()
    }
}

#[async_trait]
impl ObservabilityMetricsCollector for MockObservabilityMetricsCollector {
    async fn record_business_metric(&self, metric_name: &str, value: f64, labels: Labels, context: Option<&ObservabilityContext>) -> ServiceResult<()> {
        let mut metrics = self.metrics.write().await;
        let context_info = context.map(|c| format!("{}:{}", c.service_name, c.operation_name))
            .unwrap_or_else(|| "no_context".to_string());
        metrics.push(format!("business:{}:{}:{:?}:{}", metric_name, value, labels, context_info));
        Ok(())
    }

    async fn record_performance_metric(&self, operation: &str, duration_ms: f64, context: Option<&ObservabilityContext>) -> ServiceResult<()> {
        let mut metrics = self.metrics.write().await;
        let context_info = context.map(|c| format!("{}:{}", c.service_name, c.operation_name))
            .unwrap_or_else(|| "no_context".to_string());
        metrics.push(format!("performance:{}:{}:{}", operation, duration_ms, context_info));
        Ok(())
    }

    async fn record_error_metric(&self, error_type: &str, context: Option<&ObservabilityContext>) -> ServiceResult<()> {
        let mut metrics = self.metrics.write().await;
        let context_info = context.map(|c| format!("{}:{}", c.service_name, c.operation_name))
            .unwrap_or_else(|| "no_context".to_string());
        metrics.push(format!("error:{}:{}", error_type, context_info));
        Ok(())
    }

    fn name(&self) -> &str {
        "mock_observability"
    }

    fn is_enabled(&self) -> bool {
        true
    }
}

/// 测试观测性上下文
#[tokio::test]
async fn test_observability_context() {
    let mut context = ObservabilityContext::new("test-service".to_string(), "test-operation".to_string());
    
    // 验证初始属性
    assert_eq!(context.service_name, "test-service");
    assert_eq!(context.operation_name, "test-operation");
    assert!(!context.trace_id.is_empty());
    assert!(!context.span_id.is_empty());
    assert!(context.parent_span_id.is_none());
    assert!(context.is_active());
    
    // 添加标签和属性
    context.add_label("env".to_string(), "test".to_string());
    context.add_attribute("request_id".to_string(), serde_json::Value::String("12345".to_string()));
    
    assert!(context.labels.contains_key("env"));
    assert_eq!(context.get_label("env"), Some(&"test".to_string()));
    assert!(context.attributes.contains_key("request_id"));
    assert_eq!(context.get_attribute("request_id"), Some(&serde_json::Value::String("12345".to_string())));
    
    // 测试子上下文创建
    let child_context = context.create_child("child-operation".to_string());
    assert_eq!(child_context.trace_id, context.trace_id);
    assert_ne!(child_context.span_id, context.span_id);
    assert_eq!(child_context.parent_span_id, Some(context.span_id.clone()));
    assert_eq!(child_context.operation_name, "child-operation");
    assert_eq!(child_context.labels, context.labels); // 标签应该被继承
    
    // 测试状态变更
    context.complete();
    assert!(context.is_completed());
    assert!(!context.is_active());
    
    let mut error_context = ObservabilityContext::new("error-service".to_string(), "error-op".to_string());
    error_context.mark_error("测试错误".to_string());
    assert!(error_context.has_error());
    assert_eq!(error_context.get_error(), Some(&"测试错误".to_string()));
}

/// 测试上下文管理器
#[tokio::test]
async fn test_context_manager() {
    let manager = ContextManager::new();
    
    // 测试存储和获取上下文
    let context = ObservabilityContext::new("test-service".to_string(), "test-op".to_string());
    let context_id = context.trace_id.clone();
    
    manager.store_context(context_id.clone(), context.clone()).await;
    
    let retrieved_context = manager.get_context(&context_id).await;
    assert!(retrieved_context.is_some());
    assert_eq!(retrieved_context.unwrap().trace_id, context_id);
    
    // 测试上下文计数
    assert_eq!(manager.active_count().await, 1);
    
    // 测试上下文更新
    let updated = manager.update_context(&context_id, |ctx| {
        ctx.add_label("updated".to_string(), "true".to_string());
    }).await;
    assert!(updated);
    
    // 测试上下文移除
    let removed_context = manager.remove_context(&context_id).await;
    assert!(removed_context.is_some());
    assert_eq!(manager.active_count().await, 0);
    
    // 测试统计信息
    let stats = manager.get_stats().await;
    assert_eq!(stats.total_count, 0);
}

/// 测试追踪处理器
#[tokio::test]
async fn test_tracing_processor() {
    let config = TracingProcessorConfig::default();
    let processor = MemoryTracingProcessor::new("test_processor".to_string(), config);
    
    assert_eq!(processor.name(), "test_processor");
    assert!(processor.is_enabled());
    
    let context = ObservabilityContext::new("trace-service".to_string(), "trace-op".to_string());
    
    // 测试开始span
    processor.start_span(&context).await.unwrap();
    
    let spans = processor.get_spans().await;
    assert_eq!(spans.len(), 1);
    assert_eq!(spans[0].trace_id, context.trace_id);
    assert_eq!(spans[0].operation_name, "trace-op");
    
    // 测试添加事件
    let mut attributes = HashMap::new();
    attributes.insert("key".to_string(), serde_json::json!("value"));
    processor.add_event(&context, "test_event", attributes).await.unwrap();
    
    let events = processor.get_events().await;
    assert_eq!(events.len(), 1);
    assert_eq!(events[0].name, "test_event");
    
    // 测试结束span
    processor.end_span(&context).await.unwrap();
    
    // 测试导出
    processor.export().await.unwrap();
    
    // 测试统计
    let stats = processor.get_stats().await;
    assert_eq!(stats.total_spans, 1);
    assert_eq!(stats.total_events, 1);
}

/// 测试日志管理器
#[tokio::test]
async fn test_log_manager() {
    let config = LogManagerConfig::default();
    let manager = MemoryLogManager::new("test_logger".to_string(), config);
    
    assert_eq!(manager.name(), "test_logger");
    assert!(manager.is_enabled());
    
    let context = ObservabilityContext::new("log-service".to_string(), "log-op".to_string());
    
    // 测试基础日志记录
    manager.log(LogLevel::Info, "测试日志消息", Some(&context)).await.unwrap();
    
    let logs = manager.get_logs().await;
    assert_eq!(logs.len(), 1);
    assert_eq!(logs[0].message, "测试日志消息");
    assert_eq!(logs[0].level, LogLevel::Info);
    assert_eq!(logs[0].trace_id, Some(context.trace_id.clone()));
    
    // 测试结构化日志记录
    let mut fields = HashMap::new();
    fields.insert("user_id".to_string(), serde_json::json!("12345"));
    fields.insert("action".to_string(), serde_json::json!("login"));
    
    manager.log_structured(LogLevel::Debug, "用户登录", fields.clone(), Some(&context)).await.unwrap();
    
    let logs = manager.get_logs().await;
    assert_eq!(logs.len(), 2);
    assert_eq!(logs[1].message, "用户登录");
    assert_eq!(logs[1].fields, fields);
    
    // 测试按级别获取日志
    let info_logs = manager.get_logs_by_level(LogLevel::Info).await;
    assert_eq!(info_logs.len(), 1);
    
    // 测试按追踪ID获取日志
    let trace_logs = manager.get_logs_by_trace_id(&context.trace_id).await;
    assert_eq!(trace_logs.len(), 2);
    
    // 测试统计
    let stats = manager.get_stats().await;
    assert_eq!(stats.total_entries, 2);
    assert_eq!(stats.info_entries, 1);
    assert_eq!(stats.debug_entries, 1);
}

/// 测试统一观测性管理器
#[tokio::test]
async fn test_unified_observability_manager() {
    let config = ObservabilityConfig::default();
    let metrics_collector = Arc::new(MockMetricsCollector::new());
    let tracing_processor = Arc::new(MemoryTracingProcessor::new("test".to_string(), TracingProcessorConfig::default()));
    let log_manager = Arc::new(MemoryLogManager::new("test".to_string(), LogManagerConfig::default()));
    let observability_metrics = Arc::new(MockObservabilityMetricsCollector::new());
    
    let manager = UnifiedObservabilityManager::new(config)
        .with_metrics_collector(metrics_collector.clone())
        .with_tracing_processor(tracing_processor.clone())
        .with_log_manager(log_manager.clone())
        .with_observability_metrics(observability_metrics.clone());
    
    // 测试启动上下文
    let context_id = manager.start_context("test-service".to_string(), "test-op".to_string()).await.unwrap();
    assert!(!context_id.is_empty());
    
    // 测试添加上下文属性
    manager.add_context_attribute(&context_id, "key".to_string(), serde_json::json!("value")).await.unwrap();
    
    // 测试记录指标
    let mut labels = HashMap::new();
    labels.insert("service".to_string(), "test".to_string());
    manager.record_counter("test_counter", 1.0, labels.clone()).await.unwrap();
    manager.record_gauge("test_gauge", 100.0, labels.clone()).await.unwrap();
    manager.record_histogram("test_histogram", 50.0, labels).await.unwrap();
    
    // 测试记录日志
    manager.log(LogLevel::Info, "测试日志", None).await.unwrap();
    
    // 测试记录错误
    manager.record_error(&context_id, "测试错误").await.unwrap();
    
    // 测试结束上下文
    manager.end_context(&context_id).await.unwrap();
    
    // 验证数据收集
    let metrics = metrics_collector.get_metrics().await;
    assert!(metrics.len() >= 3); // 至少有counter、gauge、histogram
    
    let spans = tracing_processor.get_spans().await;
    assert_eq!(spans.len(), 1);
    
    let logs = log_manager.get_logs().await;
    assert!(logs.len() >= 2); // 至少有info日志和error日志
    
    let observability_metrics_data = observability_metrics.get_metrics().await;
    assert!(!observability_metrics_data.is_empty());
}

/// 测试观测性中间件
#[tokio::test]
async fn test_observability_middleware() {
    let config = ObservabilityConfig::default();
    let manager = Arc::new(create_manager_with_config(config));
    let middleware = ObservabilityMiddleware::new(manager.clone(), "middleware-service".to_string());
    
    // 测试成功操作包装
    let result = middleware.wrap_operation("success_op", async {
        Ok::<i32, ServiceError>(42)
    }).await;
    
    assert!(result.is_ok());
    assert_eq!(result.unwrap(), 42);
    
    // 测试失败操作包装
    let result = middleware.wrap_operation("failed_op", async {
        Err::<i32, ServiceError>(ServiceError::InternalError("模拟失败".to_string()))
    }).await;
    
    assert!(result.is_err());
    
    // 测试HTTP请求包装
    let result = middleware.wrap_http_request("GET", "/users", async {
        Ok::<String, ServiceError>("users data".to_string())
    }).await;
    
    assert!(result.is_ok());
    assert_eq!(result.unwrap(), "users data");
}

/// 测试批量操作中间件
#[tokio::test]
async fn test_batch_operation_middleware() {
    let config = ObservabilityConfig::default();
    let manager = Arc::new(create_manager_with_config(config));
    let batch_middleware = BatchOperationMiddleware::new(manager.clone(), "batch-service".to_string());
    
    // 测试批量操作
    let batch_size = 100;
    let result = batch_middleware.wrap_batch_operation("process_users", batch_size, async {
        // 模拟批量处理
        tokio::time::sleep(tokio::time::Duration::from_millis(10)).await;
        Ok::<usize, ServiceError>(batch_size)
    }).await;
    
    assert!(result.is_ok());
    assert_eq!(result.unwrap(), batch_size);
}

/// 测试并发上下文管理
#[tokio::test]
async fn test_concurrent_context_management() {
    let config = ObservabilityConfig::default();
    let manager = Arc::new(create_manager_with_config(config));
    
    // 并发创建和管理上下文
    let mut handles = Vec::new();
    for i in 0..10 {
        let manager_clone = manager.clone();
        let handle = tokio::spawn(async move {
            let context_id = manager_clone.start_context(
                format!("service_{}", i),
                format!("operation_{}", i)
            ).await.unwrap();
            
            // 模拟一些工作
            manager_clone.record_counter(&format!("metric_{}", i), i as f64, HashMap::new()).await.unwrap();
            manager_clone.log(LogLevel::Info, &format!("处理任务 {}", i), None).await.unwrap();
            
            manager_clone.end_context(&context_id).await.unwrap();
            i
        });
        handles.push(handle);
    }
    
    // 等待所有任务完成
    for handle in handles {
        handle.await.unwrap();
    }
    
    // 验证所有上下文都已正确处理
    assert_eq!(manager.get_active_contexts_count().await, 0);
}

/// 测试配置验证
#[tokio::test]
async fn test_config_validation() {
    let mut config = ObservabilityConfig::default();
    
    // 测试有效配置
    assert!(config.validate().is_ok());
    
    // 测试无效采样率
    config.sampling.trace_sampling_rate = 1.5;
    assert!(config.validate().is_err());
    
    config.sampling.trace_sampling_rate = -0.1;
    assert!(config.validate().is_err());
    
    // 重置为有效值
    config.sampling.trace_sampling_rate = 0.5;
    assert!(config.validate().is_ok());
    
    // 测试无效批处理大小
    config.export.batch_size = 0;
    assert!(config.validate().is_err());
    
    // 测试无效导出间隔
    config.export.batch_size = 100;
    config.export.export_interval_ms = 0;
    assert!(config.validate().is_err());
}

/// 测试观测性装饰器
#[tokio::test]
async fn test_observability_decorator() {
    let config = ObservabilityConfig::default();
    let manager = Arc::new(create_manager_with_config(config));
    let decorator = ObservabilityDecorator::new(manager.clone(), "decorator-service".to_string());
    
    // 测试函数装饰
    let result = decorator.decorate("test_function", async {
        // 模拟函数执行
        tokio::time::sleep(tokio::time::Duration::from_millis(10)).await;
        Ok::<String, ServiceError>("function result".to_string())
    }).await;
    
    assert!(result.is_ok());
    assert_eq!(result.unwrap(), "function result");
}

/// 性能测试
#[tokio::test]
async fn test_observability_performance() {
    let config = ObservabilityConfig::default();
    let manager = Arc::new(create_manager_with_config(config));
    
    let start_time = std::time::Instant::now();
    let iterations = 1000;
    
    // 测试大量上下文创建和销毁的性能
    for i in 0..iterations {
        let context_id = manager.start_context("perf-service".to_string(), format!("op_{}", i)).await.unwrap();
        manager.record_counter("perf_counter", 1.0, HashMap::new()).await.unwrap();
        manager.end_context(&context_id).await.unwrap();
    }
    
    let duration = start_time.elapsed();
    let ops_per_sec = iterations as f64 / duration.as_secs_f64();
    
    println!("性能测试: {} 次操作耗时 {:?}, 每秒操作数: {:.2}", iterations, duration, ops_per_sec);
    
    // 确保性能在合理范围内（这个阈值可以根据实际需求调整）
    assert!(ops_per_sec > 100.0, "观测性操作性能低于预期: {} ops/sec", ops_per_sec);
}

/// 测试上下文序列化
#[tokio::test]
async fn test_context_serialization() {
    let mut context = ObservabilityContext::new("serialization-service".to_string(), "serialize-op".to_string());
    context.add_label("env".to_string(), "test".to_string());
    context.add_attribute("request_id".to_string(), serde_json::json!("12345"));
    
    // 测试序列化
    let json = context.to_json().unwrap();
    assert!(!json.is_empty());
    
    // 测试反序列化
    let deserialized_context = ObservabilityContext::from_json(&json).unwrap();
    assert_eq!(deserialized_context.trace_id, context.trace_id);
    assert_eq!(deserialized_context.service_name, context.service_name);
    assert_eq!(deserialized_context.labels, context.labels);
    assert_eq!(deserialized_context.attributes, context.attributes);
}

/// 测试NoOp实现
#[tokio::test]
async fn test_noop_implementations() {
    let noop_tracing = NoOpTracingProcessor::new();
    let noop_logging = NoOpLogManager::new();
    
    assert_eq!(noop_tracing.name(), "noop");
    assert!(!noop_tracing.is_enabled());
    
    assert_eq!(noop_logging.name(), "noop");
    assert!(!noop_logging.is_enabled());
    
    let context = ObservabilityContext::new("noop-service".to_string(), "noop-op".to_string());
    
    // 所有NoOp操作都应该成功且无副作用
    noop_tracing.start_span(&context).await.unwrap();
    noop_tracing.end_span(&context).await.unwrap();
    noop_tracing.add_event(&context, "test", HashMap::new()).await.unwrap();
    noop_tracing.export().await.unwrap();
    
    noop_logging.log(LogLevel::Info, "test", Some(&context)).await.unwrap();
    noop_logging.log_structured(LogLevel::Info, "test", HashMap::new(), Some(&context)).await.unwrap();
    noop_logging.export().await.unwrap();
}

/// 辅助函数：创建用于测试的管理器
fn create_test_manager() -> UnifiedObservabilityManager {
    let config = ObservabilityConfig::default();
    let metrics_collector = Arc::new(MockMetricsCollector::new());
    let tracing_processor = Arc::new(MemoryTracingProcessor::new("test".to_string(), TracingProcessorConfig::default()));
    let log_manager = Arc::new(MemoryLogManager::new("test".to_string(), LogManagerConfig::default()));
    
    UnifiedObservabilityManager::new(config)
        .with_metrics_collector(metrics_collector)
        .with_tracing_processor(tracing_processor)
        .with_log_manager(log_manager)
}